

#include "world.h"

#include "../../engine.h"

#include "../../User.h"

#include "../../NResource/Static.h"

#include "../../NLogic/Static.h"
#include "../../NLogic/Function.h"
#include "../../NLogic/QuestInfo.h"
#include "../../NLogic/Function.h"
#include "../../GameLog.h"

namespace ProjectZ { namespace NCommand { namespace NWorld {

void CS_REQ_QUEST_UPDATE_STATE::OnExecute(User * pUser, ::Network::Packet * pPacket)
{
	/*
	 * CS_REQ_QUEST_UPDATE_STATE	0x2002		/// 퀘스트 상태 변경
		{
			u16 		u16_tid;	// QUEST_ID
			s8		s8_state;	// 상태
			u8		u8_idx;		// list index 새로 시작되는 퀘스트에 경우는 이 데이터가 필요함..


		}

		SC_REQ_QUEST_UPDATE_STATE	0x2003		/// 퀘스트 상태 변경
		{
			s16		s16_ack;	// 상태 변경 ack
			u16 		u16_tid;	// QUEST_ID
			s8		s8_state;
		}
	 */

	/*
		QS_NONE,		/// -1: 퀘스트 미부여/미진행
		QS_STARTABLE,		/// 0 : 퀘스트 시작 가능
		QS_PROGRESS,		/// 1 : 퀘스트 진행 중
		QS_SUCCESS,		/// 2 : 퀘스트 완료 가능
		QS_COMPLETE,		/// 3 : 퀘스트 완결
		QS_FAILED,		/// 4 : 퀘스트 실패
	*/

	STRESSLOG("[CHANNEL] CS_REQ_QUEST_UPDATE_STATE::ONEXECUTE");

	NLogic::QuestInfo * pQuestInfo = pUser->GetQuestInfo();
	if (NULL == pQuestInfo)
	{
		return;
	}

	PREPARE_PACKET;

	uint16_t 	u16_tid = 0;
	int8_t	s8_state = 0;
	uint8_t	u8_idx = 0;

	* pPacket >> u16_tid >> s8_state >> u8_idx;

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

	if (true == pQuestInfo->IsExistQuestHistory(u16_tid))
	{
		* pAck << static_cast<int16_t>(ACK_ALREADY_END_QUEST);
		* pAck << u16_tid << s8_state;
		pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
		pUser->Send(pAck);

		return;
	}

	NLogic::QuestInfo::Quest * pQuest = pQuestInfo->GetQuest(u16_tid);
	if (NULL == pQuest)
	{
		NLogic::QuestInfo::Quest::Data clsData;
		clsData._questID 	= u16_tid;
		clsData._idx 		= u8_idx;
		clsData._state 	= s8_state;
		clsData._achieve 	= 0;

		pQuest = NLogic::Static::InstancePtr()->GETQUESTPOOL()->NEW();
		pQuest->Open(clsData, pUser);


//		if (false == pQuestInfo->InsertQuestInfo())
//		{
//			* pAck << static_cast<int16_t>(ACK_DB_ERROR);
//			* pAck << u16_tid << s8_state;
//			pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
//			pUser->Send(pAck);
//
//			return;
//		}

		if (false == pQuestInfo->AddQuest(pQuest))
		{
			* pAck << static_cast<int16_t>(ACK_DB_ERROR);
			* pAck << u16_tid << s8_state;
			pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
			pUser->Send(pAck);

			return;
		}

		if (3 != s8_state)
		{
			* pAck << static_cast<int16_t>(ACK_OK);
			* pAck << u16_tid << s8_state;
			pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
			pUser->Send(pAck);
			return;
		}
	}

	if (-1 == s8_state)
	{
		uint8_t oldQuestState = pQuest->GetData()._state;
		pQuest->GetData()._state = s8_state;

		if (false == pQuest->UpdateQuestState())
		{
			pQuest->GetData()._state = oldQuestState;

			* pAck << static_cast<int16_t>(ACK_DB_ERROR);
			* pAck << u16_tid << s8_state;
			pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
			pUser->Send(pAck);

			return;
		}

		if (false == pQuestInfo->RemoveQuestOnlyTree(u16_tid))
		{
		}

		* pAck << static_cast<int16_t>(ACK_OK);
		* pAck << u16_tid << s8_state;
		pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
		pUser->Send(pAck);
		return;
	}

	if (3 != s8_state)
	{
		uint8_t oldQuestState = pQuest->GetData()._state;
		pQuest->GetData()._state = s8_state;

		if (false == pQuest->UpdateQuestState())
		{
			pQuest->GetData()._state = oldQuestState;

			* pAck << static_cast<int16_t>(ACK_DB_ERROR);
			* pAck << u16_tid << s8_state;
			pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
			pUser->Send(pAck);

			return;
		}

		* pAck << static_cast<int16_t>(ACK_OK);
		* pAck << u16_tid << s8_state;
		pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
		pUser->Send(pAck);
		return;
	}

	uint8_t oldQuestState = pQuest->GetData()._state;
	pQuest->GetData()._state = s8_state;
	DEBUGLOG("CS_REQ_QUEST_UPDATE_STATE state : %d", s8_state);

	if (false == pQuestInfo->RemoveQuest(u16_tid))
	{
		pQuest->GetData()._state = oldQuestState;

		* pAck << static_cast<int16_t>(ACK_DB_ERROR);
		* pAck << u16_tid << s8_state;
		pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
		pUser->Send(pAck);
		return;
	}

//	// D/B 업데이트는 성공인가??
//	if ( false == pQuest->UpdateQuestState())
//	{
//		* pAck << static_cast<int16_t>(ACK_DB_ERROR);
//		* pAck << u16_tid << s8_state;
//		pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
//		pUser->Send(pAck);
//		return;
//	}
//
//	pQuestInfo->AddQuestHistory(u16_tid);
//	pQuestInfo->RemoveQuest(u16_tid);

	pUser->FlushCharacterInfoCache();

	* pAck << static_cast<int16_t>(ACK_OK);
	* pAck << u16_tid << s8_state;
	pAck->MakePacket(CMD_SC_REQ_QUEST_UPDATE_STATE);
	pUser->Send(pAck);

	// reward exp
	NResource::QuestResource::Flyweight * pFly = NResource::Static::Instance().GetQuest()->GetFly(u16_tid);
	if (NULL == pFly)
	{
		DEBUGLOG("CS_REQ_QUEST_UPDATE_STATE NULL == pFly TID : %d", u16_tid);
		return;
	}

	DEBUGLOG("CS_REQ_QUEST_UPDATE_STATE pFly->_EXP : %d", pFly->_EXP);
	if (0 < pFly->_EXP)
	{
		ProjectZ::NLogic::NFunction::IncreaseExp(pUser, pFly->_EXP);
	}

	if (0 < pFly->_MONEY)
	{
//		pUser->GetCharacterInfo().gold += pFly->_MONEY;
		NLogic::NFunction::ModifyGold(pUser, pFly->_MONEY);
		NGameLog::LogGoldInfo(pUser, QUEST, pFly->_MONEY);

	}
}

} /*NWorld*/ } /*NCommand*/ } /*ProjectZ*/
